import android.annotation.SuppressLint
import android.app.Activity
import android.content.pm.PackageManager
import android.os.Environment
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import java.io.BufferedWriter
import java.io.File
import java.io.FileWriter
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*

fun requireWriteAndReadPermission(activity: Activity) {
    if (ContextCompat.checkSelfPermission(
            activity,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        ActivityCompat.requestPermissions(
            activity,
            arrayOf(android.Manifest.permission.WRITE_EXTERNAL_STORAGE),
            1
        )
    }
    if (ContextCompat.checkSelfPermission(
            activity,
            android.Manifest.permission.READ_EXTERNAL_STORAGE
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        ActivityCompat.requestPermissions(
            activity,
            arrayOf(android.Manifest.permission.READ_EXTERNAL_STORAGE),
            1
        )
    }
}

object Logger {

    enum class LogType {
        V, D, I, W, E
    }

    data class LoggerConfig(
        val dir: String,
        val logName: String,
        val logType: LogType = LogType.V,
        val saveDays: Int = 7
    )

    private var ENABLE = true // 日志是否可用，总开关
    private var WRITE_TO_FILE = true
    private var initialized = false
    private lateinit var DIR: String
    private lateinit var LOG_NAME: String
    private var SAVE_DAYS = 7
    private var LOG_TYPE = LogType.V

    @SuppressLint("SimpleDateFormat")
    private val loggerSdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    @SuppressLint("SimpleDateFormat")
    private val loggerFileSdf = SimpleDateFormat("yyyy-MM-dd")

    var logEntryFormat: (time: String, logType: LogType, tag: String, content: String) -> String =
        { time, logType, tag, content -> "$time: $logType-$tag-$content" }

    fun enable() {
        ENABLE = true
    }

    fun disable() {
        ENABLE = false
    }

    fun initialize(config: LoggerConfig) {
        config.run {
            DIR = dir
            LOG_NAME = logName
            SAVE_DAYS = saveDays
            LOG_TYPE = logType
        }
        initialized = true
    }

    fun w(tag: String, msg: Any) { // 警告信息
        log(tag, msg.toString(), LogType.W)
    }

    fun e(tag: String, msg: Any) { // 错误信息
        log(tag, msg.toString(), LogType.E)
    }

    fun d(tag: String, msg: Any) {// 调试信息
        log(tag, msg.toString(), LogType.D)
    }

    fun i(tag: String, msg: Any) {//
        log(tag, msg.toString(), LogType.I)
    }

    fun v(tag: String, msg: Any) {
        log(tag, msg.toString(), LogType.V)
    }

    fun w(tag: String, text: String) {
        log(tag, text, LogType.W)
    }

    fun e(tag: String, text: String) {
        log(tag, text, LogType.E)
    }

    fun d(tag: String, text: String) {
        log(tag, text, LogType.D)
    }

    fun i(tag: String, text: String) {
        log(tag, text, LogType.I)
    }

    fun v(tag: String, text: String) {
        log(tag, text, LogType.V)
    }

    /**
     * 根据tag, msg和等级，输出日志
     *
     * @param tag
     * @param msg
     * @param level
     */
    private fun log(tag: String, msg: String, level: LogType) {
        if (ENABLE) {//日志文件总开关
            if (LogType.E == level && (LogType.E == LOG_TYPE || LogType.V == LOG_TYPE)) { // 输出错误信息
                Log.e(tag, msg)
            } else if (LogType.W == level && (LogType.W == LOG_TYPE || LogType.V == LOG_TYPE)) {
                Log.w(tag, msg)
            } else if (LogType.D == level && (LogType.D == LOG_TYPE || LogType.V == LOG_TYPE)) {
                Log.d(tag, msg)
            } else if (LogType.I == level && (LogType.D == LOG_TYPE || LogType.V == LOG_TYPE)) {
                Log.i(tag, msg)
            } else {
                Log.v(tag, msg)
            }
            if (WRITE_TO_FILE && initialized) {
                //日志写入文件开关
                writeLogToFile(level, tag, msg)
            }
        }
    }

    /**
     * 打开日志文件并写入日志
     *
     * @param logType
     * @param tag
     * @param text
     */
    private fun writeLogToFile(logType: LogType, tag: String, text: String) {// 新建或打开日志文件
        val nowTime = Date()
        val needWriteFile = loggerFileSdf.format(nowTime)
        val needWriteMessage = logEntryFormat(loggerSdf.format(nowTime), logType, tag, text)
        // val dirPath = Environment.getExternalStorageDirectory()

        val dirsFile = File(DIR)
        if (!dirsFile.exists()) {
            dirsFile.mkdirs()
        }

        val file = File(dirsFile.toString(), "$needWriteFile-$LOG_NAME")// MYLOG_PATH_SDCARD_DIR
        if (!file.exists()) {
            try {
                //在指定的文件夹中创建文件
                file.createNewFile()
            } catch (e: Exception) {
            }
        }

        try {
            val filerWriter = FileWriter(file, true)// 后面这个参数代表是不是要接上文件中原来的数据，不进行覆盖
            val bufWriter = BufferedWriter(filerWriter)
            bufWriter.write(needWriteMessage)
            bufWriter.newLine()
            bufWriter.close()
            filerWriter.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    /**
     * 删除制定的日志文件
     */
    fun delFile() {// 删除日志文件
        val needDelFile = loggerFileSdf.format(getDateBefore())
        val dirPath = Environment.getExternalStorageDirectory()
        val file = File(dirPath, "$needDelFile-$LOG_NAME")// MYLOG_PATH_SDCARD_DIR
        if (file.exists()) {
            file.delete()
        }
    }

    /**
     * 得到现在时间前的几天日期，用来得到需要删除的日志文件名
     */
    private fun getDateBefore(): Date {
        val nowTime = Date()
        val now = Calendar.getInstance()
        now.time = nowTime
        now.set(Calendar.DATE, now.get(Calendar.DATE) - SAVE_DAYS)
        return now.time
    }
}